package dark

func (css Str) CSSSelectParse() (tag, id, class, attrKey, attrVal Str) {
	css = css.Trim()
	className := ""
	idName := ""
	attr := Str("")
	if css.In(".") {
		className = css.Find(`\.([\w\-]+)`)[0].Str()
	}

	if css.In("#") {
		idName = css.Find(`\#([\w\-]+)`)[0].Str()
	}
	if css.In("[") && css.In("]") {

		attr = css.ExtractRaw("[", "]")[0]
		// log.Fatal("sss:", attr)
	}

	tag = css.Replace(" ", "").Replace(".", "").Replace(className, "").Replace("#", "").Replace(idName, "").Replace(attr.Str(), "")
	attrKey = ""
	attrVal = ""
	id = Str(idName)
	class = Str(className)
	if attr != "" {
		fs := attr.Slice(1, -1).Split("=", 2)
		attrKey = fs[0]
		if fs.Len() > 1 {
			attrVal = fs[1].Word()
		}
	}
	return
}

func (str Str) XmlCssSelect(css Str) (eles Strs) {
	levelBodys := Strs{str}
	css.Trim().Split(">").Every(func(no int, levelcss Str) {
		newlevls := Strs{}
		levelcss = levelcss.Trim()
		levelBodys.Every(func(no int, body Str) {
			newlevls = newlevls.Add(body.cssSelectOneLevel(levelcss)...)
		})

		levelBodys = newlevls
	})
	return levelBodys
}

func (str Str) XMLAttrs() (attrs Dict[Str]) {
	attrs = make(Dict[Str])
	key := ""
	val := Str("")
	str.Find(`(\w+?)=[\'\"](.+?)[\'\"]`).Every(func(no int, c Str) {
		if no%2 == 0 {
			key = c.Str()
		} else {
			val = c.Trim()
			if key != "" {
				attrs[key] = val
			}
		}
	})
	// fmt.Println(attrs)
	return
}

func (str Str) cssSelectOneLevel(css Str) (selected Strs) {
	pres := Strs{}
	tag, id, class, attrKey, attrVal := css.CSSSelectParse()
	// fmt.Println("clas:", class, "tag:", tag, "id:", id, "attr:", attrKey, attrVal)
	str.Find(`(\<\w+.+?\>)`).Sort(SortLen).Every(func(no int, t Str) {
		tagName := t.Find(`\<(\w+)`)[0]

		if tag != "" && tagName != tag {
			return
		}
		hit := true
		attrs := t.XMLAttrs()
		// t.Println()
		if class != "" {
			if v, ok := attrs["class"]; !ok || !v.In(class) {
				// fmt.Println("c:", t)
				hit = false
			}
		}
		if id != "" {
			// fmt.Println("id:")
			if v, ok := attrs["id"]; !ok || v != id {
				// fmt.Println("i:", t)
				hit = false
			}
		}
		if attrKey != "" {
			if v, ok := attrs[attrKey.Str()]; !ok || (attrVal != "" && v != attrVal) {

				hit = false
			}

		}

		if hit {
			ttag := t + "|-----|" + "</" + t.Find(`\<(\w+)`)[0] + ">"
			if !pres.In(ttag) {
				pres = pres.Add(ttag)

			}
		}
	})
	pres.Every(func(no int, e Str) {
		fs := e.Split("|-----|", 2)
		start := fs[0]
		end := fs[1]

		// start.Println()
		strbak := str
		strbak.ExtractRaw(start.Str(), end.Str()).Every(func(no int, hitEle Str) {
			// hitEle.Color("B").Println()
			selected = selected.Add(hitEle)
			// strbak = strbak.Replace(hitEle.Str(), string(Str("").RandStr(8)))
		})
	})
	return selected
}
